package com.sheng.leetcode.year2023.month01.day09;

import org.junit.Test;

/**
 * @author liusheng
 * @date 2023/01/09
 * <p>
 * 1806. 还原排列的最少操作步数<p>
 * <p>
 * 给你一个偶数 n ，已知存在一个长度为 n 的排列 perm ，其中 perm[i] == i（下标 从 0 开始 计数）。<p>
 * 一步操作中，你将创建一个新数组 arr ，对于每个 i ：<p>
 * 如果 i % 2 == 0 ，那么 arr[i] = perm[i / 2]<p>
 * 如果 i % 2 == 1 ，那么 arr[i] = perm[n / 2 + (i - 1) / 2]<p>
 * 然后将 arr 赋值给 perm 。<p>
 * 要想使 perm 回到排列初始值，至少需要执行多少步操作？返回最小的 非零 操作步数。<p>
 * <p>
 * 示例 1：<p>
 * 输入：n = 2<p>
 * 输出：1<p>
 * 解释：最初，perm = [0,1]<p>
 * 第 1 步操作后，perm = [0,1]<p>
 * 所以，仅需执行 1 步操作<p>
 * <p>
 * 示例 2：<p>
 * 输入：n = 4<p>
 * 输出：2<p>
 * 解释：最初，perm = [0,1,2,3]<p>
 * 第 1 步操作后，perm = [0,2,1,3]<p>
 * 第 2 步操作后，perm = [0,1,2,3]<p>
 * 所以，仅需执行 2 步操作<p>
 * <p>
 * 示例 3：<p>
 * 输入：n = 6<p>
 * 输出：4<p>
 * <p>
 * 提示：<p>
 * 2 <= n <= 1000<p>
 * n 是一个偶数<p>
 * <p>
 * 来源：力扣（LeetCode）<p>
 * 链接：<a href="https://leetcode.cn/problems/minimum-number-of-operations-to-reinitialize-a-permutation">1806. 还原排列的最少操作步数</a><p>
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。<p>
 */
public class LeetCode1806 {

    @Test
    public void test01() {
//        int n = 2;
//        int n = 4;
        int n = 6;
        System.out.println(new Solution().reinitializePermutation(n));
    }
}

class Solution {
    public int reinitializePermutation(int n) {
        /**
         * 其实就是把排好序的数组中的前半部分放到奇数位，后半部分放到偶数位
         * 赋值也为一次操作，初始值为 1
         */
        int operation = 1;
        int[] perm = new int[n];
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            perm[i] = i;
        }
        for (int i = 0; i < n; i++) {
            if (i % 2 == 0) {
                arr[i] = perm[i / 2];
            } else {
                arr[i] = perm[n / 2 + (i - 1) / 2];
            }
        }
        if (n == 2) {
            return 1;
        }
        // 欧拉定理
        int pow = 2;
        while (pow != 1) {
            operation++;
            pow = pow * 2 % (n - 1);
        }
        return operation;
    }
}
